package com.xujl.fastlib.base;

import android.content.Context;
import android.os.Bundle;
import android.os.Looper;
import android.view.MotionEvent;
import android.view.View;

import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
import com.xujl.fastlib.BR;
import com.xujl.fastlib.swipeback.SlideBackHelper;
import com.xujl.fastlib.swipeback.SlideConfig;
import com.xujl.fastlib.swipeback.callbak.OnSlideListenerAdapter;
import com.xujl.fastlib.utils.LogS;
import com.xujl.task.RxLifeList;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import androidx.annotation.DrawableRes;
import androidx.annotation.FloatRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import me.yokeyword.fragmentation.ExtraTransaction;
import me.yokeyword.fragmentation.ISupportActivity;
import me.yokeyword.fragmentation.ISupportFragment;
import me.yokeyword.fragmentation.SupportActivityDelegate;
import me.yokeyword.fragmentation.SupportHelper;
import me.yokeyword.fragmentation.anim.FragmentAnimator;

/**
 * @author xujl
 * @email 597355068@qq.com
 * @Date on 2019/6/18
 * @Description
 */
public abstract class BaseActivity<M extends BaseModel, V extends BaseView> extends RxAppCompatActivity implements IControl, ISupportActivity {
    private static final String TAG = "BaseActivity";
    protected M mModel;
    protected V mView;
    private boolean isAlive = true;
    protected RxLifeList mRxLife = new RxLifeList();
    final SupportActivityDelegate mDelegate = new SupportActivityDelegate(this);

    @Override
    protected void onCreate (@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDelegate.onCreate(savedInstanceState);
        configSwipeBack();
        initView();
        initModel(); //让ViewModel拥有View的生命周期感应
        Looper.myQueue().addIdleHandler(() -> {
            init(savedInstanceState);
            LogS.i(TAG, "-->init success");
            return false;
        });
    }

    @Override
    public void onClick (View view) {

    }

    protected abstract void init (Bundle savedInstanceState);

    @Override
    public Context exposeContext () {
        return this;
    }

    @Override
    public BaseActivity<M, V> exposeActivity () {
        return this;
    }

    private void initModel () {
        try {
            Class clz = this.getClass();
            Type type = clz.getGenericSuperclass();
            ParameterizedType pt = (ParameterizedType) type;
            Class modelClass = (Class) pt.getActualTypeArguments()[0];
            mModel = (M) modelClass.getConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            LogS.w(TAG, "反射创建mModel失败");
        }
        if (mModel == null) {
            mModel = createDefaultModel();
            if (mModel == null) {
                LogS.w(TAG, "mModel创建失败！！！");
                return;
            }
        }
        getLifecycle().addObserver(mModel);
        //注入RxLifecycle生命周期
        mModel.injectLifecycleProvider(this);
        mModel.init(this);
        mView.bindData(BR.data, mModel);
    }

    protected M createDefaultModel () {
        return (M) new BaseModel() {
            @Override
            public void init (IControl control) {

            }
        };
    }

    private void initView () {
        try {
            Class clz = this.getClass();
            Type type = clz.getGenericSuperclass();
            ParameterizedType pt = (ParameterizedType) type;
            Class viewClass = (Class) pt.getActualTypeArguments()[1];
            mView = (V) viewClass.getConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            LogS.w(TAG, "反射创建mView失败");
        }
        if (mView == null) {
            mView = createDefaultView();
            if (mView == null) {
                LogS.w(TAG, "mView创建失败！！！");
                return;
            }
        }
        setContentView(mView.createLayout(this, getClass().getSimpleName()));
        getLifecycle().addObserver(mView);
        mView.bindData(BR.control, this);
        mView.init(this);
    }

    protected V createDefaultView () {
        return (V) new BaseView() {
            @Override
            public void init (IControl control) {

            }
        };
    }

    /**
     * 配置滑动返回功能
     */
    private void configSwipeBack () {
        if (enableSwipeBack()) {
            SlideBackHelper.attach(
                    // 当前Activity
                    this, BaseConfig.getInstance().getActivityHelper(),
                    // 参数的配置
                    new SlideConfig.Builder()
                            // 屏幕是否旋转
                            .rotateScreen(false)
                            // 是否仅仅使用边缘侧滑
                            .edgeOnly(true)
                            // 是否禁止侧滑
                            .lock(false)
                            // 侧滑的响应阈值，0~1，对应屏幕宽度*percent
                            .edgePercent(0.3f)
                            // 关闭页面的阈值，0~1，对应屏幕宽度*percent
                            .slideOutPercent(0.6f).create(),
                    // 滑动的监听
                    new OnSlideListenerAdapter() {
                        @Override
                        public void onSlide (@FloatRange(from = 0.0,
                                to = 1.0) float percent) {
                            super.onSlide(percent);
                        }
                    });
        }
    }

    /**
     * 是否使用返回
     *
     * @return
     */
    public boolean enableSwipeBack () {
        return false;
    }

    @Override
    protected void onDestroy () {
        isAlive = false;
        mRxLife.onDestroy();
        mDelegate.onDestroy();
        super.onDestroy();
    }

    @Override
    public boolean isAlive () {
        return isAlive;
    }

    @Override
    public BaseView exposeView () {
        return mView;
    }

    @Override
    public BaseModel exposeModel () {
        return mModel;
    }

    //<editor-fold desc="fragmentation">
    @Override
    public SupportActivityDelegate getSupportDelegate () {
        return mDelegate;
    }

    /**
     * Perform some extra transactions.
     * 额外的事务：自定义Tag，添加SharedElement动画，操作非回退栈Fragment
     */
    @Override
    public ExtraTransaction extraTransaction () {
        return mDelegate.extraTransaction();
    }

    @Override
    protected void onPostCreate (@Nullable Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        mDelegate.onPostCreate(savedInstanceState);
    }

    /**
     * Note： return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev);
     */
    @Override
    public boolean dispatchTouchEvent (MotionEvent ev) {
        return mDelegate.dispatchTouchEvent(ev) || super.dispatchTouchEvent(ev);
    }

    /**
     * 不建议复写该方法,请使用 {@link #onBackPressedSupport} 代替
     */
    @Override
    final public void onBackPressed () {
        mDelegate.onBackPressed();
    }

    /**
     * 该方法回调时机为,Activity回退栈内Fragment的数量 小于等于1 时,默认finish Activity
     * 请尽量复写该方法,避免复写onBackPress(),以保证SupportFragment内的onBackPressedSupport()回退事件正常执行
     */
    @Override
    public void onBackPressedSupport () {
        mDelegate.onBackPressedSupport();
    }

    /**
     * 获取设置的全局动画 copy
     *
     * @return FragmentAnimator
     */
    @Override
    public FragmentAnimator getFragmentAnimator () {
        return mDelegate.getFragmentAnimator();
    }

    /**
     * Set all fragments animation.
     * 设置Fragment内的全局动画
     */
    @Override
    public void setFragmentAnimator (FragmentAnimator fragmentAnimator) {
        mDelegate.setFragmentAnimator(fragmentAnimator);
    }

    /**
     * Set all fragments animation.
     * 构建Fragment转场动画
     * <p/>
     * 如果是在Activity内实现,则构建的是Activity内所有Fragment的转场动画,
     * 如果是在Fragment内实现,则构建的是该Fragment的转场动画,此时优先级 > Activity的onCreateFragmentAnimator()
     *
     * @return FragmentAnimator对象
     */
    @Override
    public FragmentAnimator onCreateFragmentAnimator () {
        return mDelegate.onCreateFragmentAnimator();
    }

    @Override
    public void post (Runnable runnable) {
        mDelegate.post(runnable);
    }

    /****************************************以下为可选方法(Optional methods)******************************************************/

    /**
     * 加载根Fragment, 即Activity内的第一个Fragment 或 Fragment内的第一个子Fragment
     *
     * @param containerId 容器id
     * @param toFragment  目标Fragment
     */
    public void loadRootFragment (int containerId, @NonNull ISupportFragment toFragment) {
        mDelegate.loadRootFragment(containerId, toFragment);
    }

    public void loadRootFragment (int containerId, ISupportFragment toFragment, boolean addToBackStack, boolean allowAnimation) {
        mDelegate.loadRootFragment(containerId, toFragment, addToBackStack, allowAnimation);
    }

    /**
     * 加载多个同级根Fragment,类似Wechat, QQ主页的场景
     */
    public void loadMultipleRootFragment (int containerId, int showPosition, ISupportFragment... toFragments) {
        mDelegate.loadMultipleRootFragment(containerId, showPosition, toFragments);
    }

    /**
     * show一个Fragment,hide其他同栈所有Fragment
     * 使用该方法时，要确保同级栈内无多余的Fragment,(只有通过loadMultipleRootFragment()载入的Fragment)
     * <p>
     * 建议使用更明确的{@link #showHideFragment(ISupportFragment, ISupportFragment)}
     *
     * @param showFragment 需要show的Fragment
     */
    public void showHideFragment (ISupportFragment showFragment) {
        mDelegate.showHideFragment(showFragment);
    }

    /**
     * show一个Fragment,hide一个Fragment ; 主要用于类似微信主页那种 切换tab的情况
     */
    public void showHideFragment (ISupportFragment showFragment, ISupportFragment hideFragment) {
        mDelegate.showHideFragment(showFragment, hideFragment);
    }

    /**
     * It is recommended to use {@link SupportFragment#start(ISupportFragment)}.
     */
    public void start (ISupportFragment toFragment) {
        mDelegate.start(toFragment);
    }

    /**
     * It is recommended to use {@link SupportFragment#start(ISupportFragment, int)}.
     *
     * @param launchMode Similar to Activity's LaunchMode.
     */
    public void start (ISupportFragment toFragment, @ISupportFragment.LaunchMode int launchMode) {
        mDelegate.start(toFragment, launchMode);
    }

    /**
     * It is recommended to use {@link SupportFragment#startForResult(ISupportFragment, int)}.
     * Launch an fragment for which you would like a result when it poped.
     */
    public void startForResult (ISupportFragment toFragment, int requestCode) {
        mDelegate.startForResult(toFragment, requestCode);
    }

    /**
     * It is recommended to use {@link SupportFragment#startWithPop(ISupportFragment)}.
     * Start the target Fragment and pop itself
     */
    public void startWithPop (ISupportFragment toFragment) {
        mDelegate.startWithPop(toFragment);
    }

    /**
     * It is recommended to use {@link SupportFragment#startWithPopTo(ISupportFragment, Class, boolean)}.
     *
     * @see #popTo(Class, boolean)
     * +
     * @see #start(ISupportFragment)
     */
    public void startWithPopTo (ISupportFragment toFragment, Class<?> targetFragmentClass, boolean includeTargetFragment) {
        mDelegate.startWithPopTo(toFragment, targetFragmentClass, includeTargetFragment);
    }

    /**
     * It is recommended to use {@link SupportFragment#replaceFragment(ISupportFragment, boolean)}.
     */
    public void replaceFragment (ISupportFragment toFragment, boolean addToBackStack) {
        mDelegate.replaceFragment(toFragment, addToBackStack);
    }

    /**
     * Pop the fragment.
     */
    public void pop () {
        mDelegate.pop();
    }

    /**
     * Pop the last fragment transition from the manager's fragment
     * back stack.
     * <p>
     * 出栈到目标fragment
     *
     * @param targetFragmentClass   目标fragment
     * @param includeTargetFragment 是否包含该fragment
     */
    public void popTo (Class<?> targetFragmentClass, boolean includeTargetFragment) {
        mDelegate.popTo(targetFragmentClass, includeTargetFragment);
    }

    /**
     * If you want to begin another FragmentTransaction immediately after popTo(), use this method.
     * 如果你想在出栈后, 立刻进行FragmentTransaction操作，请使用该方法
     */
    public void popTo (Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable) {
        mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable);
    }

    public void popTo (Class<?> targetFragmentClass, boolean includeTargetFragment, Runnable afterPopTransactionRunnable, int popAnim) {
        mDelegate.popTo(targetFragmentClass, includeTargetFragment, afterPopTransactionRunnable, popAnim);
    }

    /**
     * 当Fragment根布局 没有 设定background属性时,
     * Fragmentation默认使用Theme的android:windowbackground作为Fragment的背景,
     * 可以通过该方法改变其内所有Fragment的默认背景。
     */
    public void setDefaultFragmentBackground (@DrawableRes int backgroundRes) {
        mDelegate.setDefaultFragmentBackground(backgroundRes);
    }

    /**
     * 得到位于栈顶Fragment
     */
    public ISupportFragment getTopFragment () {
        return SupportHelper.getTopFragment(getSupportFragmentManager());
    }

    /**
     * 获取栈内的fragment对象
     */
    public <T extends ISupportFragment> T findFragment (Class<T> fragmentClass) {
        return SupportHelper.findFragment(getSupportFragmentManager(), fragmentClass);
    }
    //</editor-fold>
}
